#pragma once
#include "Variable.h"
#include "expr.h"
class VariableFuncion:
	public Variable
{
public:

	VariableFuncion(Variable* sig,vector<Expr*> expr):Variable(sig)
	{
		this->expr=expr;
	}

	~VariableFuncion(void)
	{
	}

	void setExpr(vector<Expr*> expr){
		this->expr=expr;
	}

	vector<Expr*> getExpr(){
		return this->expr;
	}

	virtual string is(){
		return "Variable_Funcion";
	
	}
	virtual tipo_ts * validarSemantica(tabla_simbolos *tabla_de_tipo,tabla_simbolos *tabla_de_varaible){
		
		vector<item_ts*> its = tabla_de_varaible->getALL(this->getValor().append("&FP&"));
		if(its.size()>0){
			
			for(int i=0;i<its.size();i++){
				bool find = true;
				if(its.at(i)->getTipo()->is().compare("FUNCION")==0 ){
				funcion *fun = (funcion*)its.at(i)->getTipo();
				if((int)this->getExpr().size()==fun->getParams()->getTable().size()){
					for(int i=0;i<(int)this->getExpr().size();i++){
						tipo_ts *tts = this->getExpr().at(i)->validarSemantica(tabla_de_tipo,tabla_de_varaible);
						if(tts->is().compare(fun->getParams()->getTable().at(i)->getTipo()->is()) != 0){
							/*stringstream out;
							out<<"Parametro incorrecto"<<endl;
							throw exception(out.str().c_str());*/
							find = false;
						}else{
							if(fun->getParams()->getTable().at(i)->getVar()){
								if(this->getExpr().at(i)->is().compare("Literal_Identificador")!=0){
									/*stringstream out;
									out<<"Se Esperaba un literal indenditficador dentro del parametro";
									throw exception(out.str().c_str());*/
									find = false;
								}

							}

						}
					
					}

				}else{
					find = false;
				}

				if(find){
					if(fun->getTiporetorno()->is().compare("REGISTRO")==0&&this->getsig()!=0){
						registro *r = (registro*)fun->getTiporetorno();
						return this->getsig()->validarSemantica(tabla_de_tipo,r->getTs());
					}else{
					return fun->getTiporetorno();
					}
				}

			}else{
			if(its.at(i)->getTipo()->is().compare("PROCEDIMIENTO")==0 ){
				procedimiento *pro = (procedimiento*)its.at(i)->getTipo();
				if((int)this->getExpr().size()==pro->getParams()->getTable().size()){
				for(int i=0;i<(int)this->getExpr().size();i++){
					tipo_ts *tts = this->getExpr().at(i)->validarSemantica(tabla_de_tipo,tabla_de_varaible);
					if(tts->is().compare(pro->getParams()->getTable().at(i)->getTipo()->is()) != 0){
						/*stringstream out;
						out<<"Parametro incorrecto"<<endl;
						throw exception(out.str().c_str());*/
						find = false;
					}else{
						if(pro->getParams()->getTable().at(i)->getVar()){
							if(this->getExpr().at(i)->is().compare("Literal_Identificador")!=0){
								/*stringstream out;
								out<<"Se Esperaba un literal indenditficador dentro del parametro";
								throw exception(out.str().c_str());*/
								find = false;
							}
						}

						
					}
					
				}
			}else{
				find = false;
			}
				if(find){
				return 0;
				}
			}else{
				stringstream out;
				out<<"Se esperaba una funcion o un procedimiento"<<endl;
				throw exception(out.str().c_str());
				}
			}
			}

			stringstream out;
				out<<"PARAMETROS DE LA FUNCION O PROCEDIMIENTO INCORRECTOS "<<this->getValor()<<endl;
				throw exception(out.str().c_str());

			
		}else{
			stringstream out;
			out<<"Variable No exite"<<this->getValor()<<endl;
			throw exception(out.str().c_str());
		}
	}


private:
	vector<Expr*> expr;
};

